Contextual Menu Basics
Volume Number: 14
Issue Number: 1
Column Tag: Toolbox Techniques
Contextual Menu Basics
by Steve Sheets
Adding Support for the new Mac OS 8 Contextual Menu API;
even for applications running without Apple's Contextual
Menu Manager
A New OS, A New API, A New Logical Interface
The original thought that went into the Macintosh design was "ease of use". This would
be the computer for "the rest of us" who were computer novices or worse. After
awhile, novices become power users who want quicker ways to do things they already
know how to do. You can see this in the menus of the Macintosh. The user has menu
items that he can select with the mouse, but he also has Command-key short cuts. You
also can see it in drawing palettes that allow simple commands, yet can be double
clicked for more in depth configuration.
The contextual menu feature introduced with Mac OS 8 continues this idea. While
holding down the Control key, a user can click the mouse while above some information
he wants to manipulate. The information could be selected text, a picture, some
database tables or anything we traditionally think of as exportable data. A popup menu
appears to provide him with all the commands related to this data. Even if no data is
selected, the user can see commands related to the window, document or application.
Contextual menus provide no new commands that are not already available. Rather it
groups the commands in a quick table to be read and selected. Instead of selecting the
data and then selecting the command, with one quick click, the user can see what can be
accomplish. Searching for familiar commands becomes much easier. (For example, "is
Find under Edit, View or Text?") Even if the user knows exactly where the command is
in the normal menu, a Control-click on the selected data is faster. Power users will
quickly adopt Contextual Menus to get their work done.
Whenever Apple introduced a new "logical interface", they provide a new API to
developers so that we can provide this new feature to users. Luckily, the API for
contextual menu is very small and involves concepts similar to those in the Drag
Manager or even the Scrap Manager. This article explains what a developer must know
to simply add contextual menus to his application. As an additional benefit, the article
will show how easily Contextual-Menu-like features can be added to an application
runing an older version of Mac OS, where Apple has not provided the Contextual Menu
Manager.
Extension Modules
There is one exception to the idea that Contextual Menus should not provide commands
not listed anywhere else. On a PowerPC Mac with the Contextual Menu API installed,
extension modules can add additional functions. These code fragments must be installed
in a special folder in the System Folder before startup. They are then loaded and called
whenever a contextual menu is created. By looking at the data selected (text, picture,
file, folder or even no data), the extensions can add commands to the contextual menu.
These plug-ins have only read access to the selected data, so they can not modify the
data, but they can return results in the Clipboard or by sending an Apple event. The
hosting application need not concern itself with an extension module; all of a plug-in's
functions are done without the application's knowledge. The Contextual Menu Extension
Module API will be explained in an upcoming article. Until then, just be aware that it
is available, but only supported on PowerPC machines.
Adding Commands
The key to determining what to put into a contextual menu is the emphasis --
contextual menus. Ignore that the feature is a popup menu. There are many locations
to place commands, or allow short cuts to global settings. The user has selected some
content, which he wants to modify. Add commands that are based on the content of what
is clicked. In a drawing program, clicking drawing elements (circles, rect, lines)
should show the commands that affect the element (rotate, change line thickness,
change color). In a word processor, commands that change the style of the text or the
arrangement of the document are good choices. Window commands can be available,
even if the user clicks a portion of the window that has no data. Think twice before
adding an application command. For example, Quit is a poor choice; it already has a
short cut in the menu. The API provides a way for sub menus also to be added to the
contextual menu. If too many commands need to be added, this is a good way to subdivide
the list.
The API
There are only 3 new calls in the Contextual Menu API. In their easiest explanation,
the calls initialize the API, check if the contextual menu should appear, and display the
Contextual Menu. These functions should be called only if the API is installed on the
Mac. Use Gestalt to check if this is the case. The gestaltContextualMenuPresent bit of
the gestaltContextual- MenuAttr Gestalt attribute indicates if the Contextual Menu
Manager is installed.
If the Contextual Menu Manager is installed, call InitContextualMenus(). This will
register the application as a client of the Contextual Menu Manager. The routine
returns noErr (0) if the initialization succeeds. This check & initialization should
occur immediately after the standard toolbox initialization.
Listing 1: ContextualMenuFun.cp
Check if Manager Available, if so Init It
long a_result;
if (Gestalt(gestaltContextualMenuAttr, &a_result) == noErr)
g_have_contextual_menus = BitTst(&a_result,

31-gestaltContextualMenuPresent);
else
g_have_contextual_menus = false;
if (g_have_contextual_menus)
g_have_contextual_menus = (InitContextualMenus()==noErr);
To indicate he wants the contextual menu, the user does a special click on some selected
data. For Mac OS 8, this is done by holding down the Control key while doing a standard
mouse click. However, there is no reason that in the future this special click could not
be done some other way (such as a right mouse click on a two-button mouse). For this
reason, the Contextual Menu Manager provides a call that checks if the special click is
being done. IsShowContextualMenuClick() should be called after the application is
passed any non-NullEvent event. The function is passed the event record and returns
true if the special click occured. If the function returns false, the program should
continue normally.
Listing 2: ContextualMenuFun.cp
Parse Event, checking if the event is Contextual Menu special click.
If so, call routine to handle this.
a_flag = WaitNextEvent(everyEvent, &g_record, 10, NULL);
if (g_have_contextual_menus) {
// if Contextual Menus event,
if (IsShowContextualMenuClick(&g_record)) {
// Handle Contextual Menus
G_ContextualMenu(g_record);
a_flag = false;
}
}

// Handle Normal Events if flag true
The most important routine of the Contextual Menu API is ContextualMenuSelect(). It
should be called only when IsShowContextualMenuClick() has returned true. Not only
does this routine have several parameters, the application must do several
preparation tasks before it can be called.
Assuming the application knows which window was chosen, the application should
check if this window is the currently selected window. If it is not, it should
immediately be made the current selected window, and redrawn. Next, if some content
data was selected, some sort of visual feedback should be drawn to indicate this.
Inverting, either the data or the outline of the data is a common method to show what
was chosen.
Next, a menu handle should be created and inserted into the menu bar just as if the
PopUpMenuSelect() call was going to be made. At this point, the various menu items
can be added to the menu handle. Sub-menus also can be added. If the Contextual Menu
API adds any items to the list (Help or plug-ins), the Contextual Menu Manager will
handle parsing these items; your application need not worry about them.
Now call ContextualMenuSelect(). Pass it the created menu handle, the point that was
clicked (in global coordinates), a flag that must always be set to false (originally